package org.client.otdr;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.client.otdr.executor.ResolverAccessor;
import org.client.otdr.resolver.MarkerResolver;
import org.openems.BookmarkEntities;
import org.openems.entity.BooleanEntity;
import org.openems.entity.ChoiceEntity;
import org.openems.entity.Entity;
import org.openems.entity.Key;
import org.openems.entity.ListEntity;
import org.openems.entity.MarkerEntity;
import org.openems.entity.NumericEntity;
import org.openems.entity.PaneEntity;
import org.openems.entity.TableEntity;
import org.openems.entity.TextEntity;
import org.openems.entity.TraceEntity;
import org.openems.entity.Unit;

import framework.AbstractDomainService;
import framework.EntityResigter;
import framework.EntityStoreListener;
import framework.resolver.UnitResolver;
import framework.webclient.RestSocket;
import framework.webclient.SystemProperty;
import framework.webserver.WebHandler;

public class OtdrDomainService extends AbstractDomainService {

	public static final String DEVICE_REMOTE = "Remote";
	public static final String DEVICE_LOCAL = "Local";
	public static final String UPLOAD_GO = "Upload";
	public static final String UPLOAD_STOP = "Cancel";
	public static final String WAVELENGTH_1310 = "1310";
	public static final String WAVELENGTH_1550 = "1550";
	public static final String WAVELENGTH_1650 = "1650";
	public static final String PULSEWidTH_50NS = "50";
	public static final String PULSEWidTH_100NS = "100";
	public static final String MEASUREMENT_START = "Start";
	public static final String MEASUREMENT_STOP = "Stop";
	public static final String DISTANCERANGE_1KM = "1";
	public static final String DISTANCERANGE_5KM = "5";
	public static final String DISTANCERANGE_10KM = "10";
	public static final String DISTANCERANGE_50KM = "50";
	public static final String DISTANCERANGE_100KM = "100";
	public static final String AUTOSEARCH_STOP = "Stop Search";
	public static final String AUTOSEARCH_START = "Search";
		
	@Override
	protected void registerDefaultEntities(EntityResigter register) {
		OTDRID id = OTDRID.get();
		
		register.registerEntity(new ChoiceEntity(id.CONTROL, "Measurement", Arrays.asList(MEASUREMENT_STOP, MEASUREMENT_START), false));
		register.registerEntity(new ChoiceEntity(id.DEVICE, "Device", Arrays.asList(DEVICE_LOCAL, DEVICE_REMOTE), true));
		register.registerEntity(new TraceEntity(id.TRACE, "Trace", true));
		register.registerEntity(new ChoiceEntity(id.UPLOADALL, "Upload Local Data", Arrays.asList(UPLOAD_STOP, UPLOAD_GO), false));
		register.registerEntity(new ChoiceEntity(id.WAVELENGTH, "Wavelength", Arrays.asList(WAVELENGTH_1310, WAVELENGTH_1550, WAVELENGTH_1650), true));
		register.registerEntity(new ChoiceEntity(id.PULSEWIDTH, "Pulsewidth", Arrays.asList(PULSEWidTH_50NS, PULSEWidTH_100NS), true));
		register.registerEntity(new ChoiceEntity(id.DISTANCERANGE, "Range", Arrays.asList(DISTANCERANGE_1KM, DISTANCERANGE_5KM, DISTANCERANGE_10KM, DISTANCERANGE_50KM), true));
		register.registerEntity(new NumericEntity(id.ACTIVETRACERANGE, "ActiveTraceRange", 3, Unit.meter(), 0.0, Double.MAX_VALUE, true));
		register.registerEntity(new NumericEntity(id.ACTIVETRACERANGEIOR, "ActiveTraceRangeIOR", 3, Unit.meter(), 0.0, Double.MAX_VALUE, true));

		register.registerEntity(new NumericEntity(id.REALDISTANCE, "Distance", 2, new Unit(Unit.SubUnit.Kilo, Unit.Type.Meter), 0.0, Double.MAX_VALUE, true));
		register.registerEntity(new NumericEntity(id.IOR, "IOR", 5, Unit.none(), 1.2, 2.0, true));
		register.registerEntity(new NumericEntity(id.START, "Start", 2, Unit.meter(), 0.0, Double.MAX_VALUE,  true));
		register.registerEntity(new NumericEntity(id.STOP, "Stop", 2, Unit.meter(), 0.0, Double.MAX_VALUE, true));

		register.registerEntity(new ChoiceEntity(id.FILELIST, "File", false));
		register.registerEntity(new TextEntity(id.SAVENAME, "Save", false));
		register.registerEntity(new ChoiceEntity(id.BOOKMARK, "Bookmark", false));
		
		register.registerEntity(new PaneEntity(id.SETUPPANE, "Setup", true));
		register.registerEntity(new PaneEntity(id.MARKERPANE, "Marker", true));
		register.registerEntity(new PaneEntity(id.SYSTEMPANE, "System", true));
		register.registerEntity(new PaneEntity(id.BUTTONPANE, "Function", true));
		register.registerEntity(new PaneEntity(id.CHARTPANE, "Chart", true));
		register.registerEntity(new PaneEntity(id.MAP, "Map", true));
		register.registerEntity(new PaneEntity(id.REPORTPANE, "Report", true));
		register.registerEntity(new PaneEntity(id.JSCLIENT, "Web Client", true));
		register.registerEntity(new PaneEntity(id.TABLEPANE, "Table", true));
		
		register.registerEntity(new ListEntity(id.MARKERLIST, "Markers", true));
		
		register.registerEntity(new ChoiceEntity(id.AUTOSEARCH, "Auto Search", Arrays.asList(AUTOSEARCH_STOP, AUTOSEARCH_START), false));
		register.registerEntity(new MarkerEntity(id.GOOGLEMAPMARKER, "Google Map Marker", getClass().getResource("/org/client/otdr/arrow-icon.png").toExternalForm(), 5, Unit.none(), 0.0, Double.MAX_VALUE, true));

		register.registerEntity(new TableEntity(id.TABLE, "Table", true));
		register.registerEntity(new BooleanEntity(id.GOOGLEMARKERENABLED, "Map Marker", true));
	}

	@Override
	protected void initialize() {
		OTDRID id = OTDRID.get();
		
		ChoiceEntity bookmark = (ChoiceEntity)getSilentAccessor().get(id.BOOKMARK);
		RestSocket socket = super.getRestSocket();
		Map<String, String> parameter = new HashMap<String, String>();
		parameter.put("productName", this.getSystemProperty().getProductName());
		
		BookmarkEntities entities = socket.get("bookmark", BookmarkEntities.class, parameter);
		bookmark.setChoices(entities.getStringList());
		getSilentAccessor().put(bookmark);
		
		final OtdrResolver otdrResolver = new OtdrResolver();
		
		addCommand(new PostDependency(socket, this.getSystemProperty(), this.getActiveAccessor(), new ResolverAccessor() {
			@Override
			public void add(Key key, UnitResolver unitResolver) {
				otdrResolver.add(key, unitResolver);
			}
		}));
		
		
		ListEntity markers = (ListEntity)this.getActiveAccessor().get(id.MARKERLIST);
		for (Key k : markers.getKeys()) {
			otdrResolver.add(k, new MarkerResolver(k));
		}
		setDependencyResolver(otdrResolver);
	}

	protected String getOtdrFileUrl() {
		return "http://restmiyake.appspot.com/resources/otdrFiles";
	}

	@Override
	protected SystemProperty getSystemProperty() {
		return new SystemProperty() {

			@Override
			public String getProductName() {
				return "MS9740";
			}

			@Override
			public String getSerialNumber() {
				return "SN01234567890";
			}

			@Override
			public String getApplicationType() {
				return "Otdr";
			}
			
		};
	}

	@Override
	protected Object getID() {
		return OTDRID.get();
	}

	@Override
	public void webRequestReceived(String line) {
		if (line.equals("start")) {
			ChoiceEntity e = (ChoiceEntity)getEntity(OTDRID.get().CONTROL);
			e.setIndex(1);
			putEntity(e);
		}
	}

	@Override
	public void addWebHandler(final WebHandler myWebSocketHandler) {
		this.addEntityStoreListener(new EntityStoreListener() {
			@Override
			public void valueChanged(Entity entity) {
				myWebSocketHandler.stateChanged(entity.getName());
			}
        }, OTDRID.get().TRACE);
	}

	@Override
	public String getServiceName() {
		return "OTDR";
	}
}
